module Analyze
#using Plots
using Requires
using Distributions

function analyze(dirname)
    return Analyze_data(dirname)
end



mutable struct Analyze_data
    plaquette::Array{Float64,1}
    polyakov::Array{ComplexF64,1}
    trjs::Array{Int64,1}
    numdata::Int64
    dirname::String

    function Analyze_data(dirname)
        plaquette = Float64[]
        polyakov = ComplexF64[]
        trjs = Int64[]
        filename_plaquette = pwd() * "/" * dirname * "/Plaquette.txt"
        filename_polyakov = pwd() * "/" * dirname * "/Polyakov_loop.txt"
        if isfile(filename_plaquette)
            open(filename_plaquette) do f
                for i in eachline(f)
                    if occursin("plaq", i)
                        tmp = split(i)
                        itrj = parse(Int, tmp[1])
                        plaq = parse(Float64, tmp[2])
                        append!(trjs, itrj)
                        append!(plaquette, plaq)
                    end

                end
            end
        else
            println("$filename_plaquette does not exist")
        end

        if isfile(filename_polyakov)
            open(filename_polyakov) do f
                for i in eachline(f)
                    if occursin("poly", i)
                        tmp = split(i)
                        itrj = parse(Int, tmp[1])
                        poly = parse(Float64, tmp[2]) + im * parse(Float64, tmp[3])
                        append!(polyakov, poly)
                    end

                end
            end
        else
            println("$filename_polyakov does not exist")
        end

        return new(plaquette, polyakov, trjs, length(trjs), dirname)
    end
end

function get_plaquette_average(dirname::String)
    return mean(get_plaquette(dirname))
end

function get_polyakov_average(dirname::String)
    return mean(get_polyakov(dirname))
end

function get_plaquette(dirname::String)
    a = analyze(dirname)
    return a.plaquette
end

function get_polyakov(dirname::String)
    a = analyze(dirname)
    return a.polyakov
end

function get_trjs(dirname::String)
    a = analyze(dirname)
    return a.trjs
end

function get_plaquette(a::Analyze_data)
    return a.plaquette
end

function get_polyakov(a::Analyze_data)
    return a.polyakov
end

function get_trjs(a::Analyze_data)
    return a.trjs
end

function get_dirname(a::Analyze_data)
    return a.dirname
end

function __init__()
    @require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" begin
        using Plots
        function plot_plaquette(dirname::String)
            a = analyze(dirname)
            plot_plaquette(a)
        end

        function plot_plaquette(a::Analyze_data)
            plt1 = histogram([0], label = nothing) #plot1
            plt2 = plot([], [], label = nothing) #plot2
            ylabel!("Plaquette")
            xlabel!("MC time")
            plot(plt1, plt2, layout = 2)
            hist_plaq = []

            Nsteps = a.numdata

            function plot_refresh!(plt1, plt2, hist_plaq, plaq, itrj)
                bins = round(Int, log(itrj) * 5 + 1)
                append!(hist_plaq, plaq)

                plt1 = histogram(hist_plaq, bins = bins, label = nothing) #plot1
                xlabel!("Plaquette")

                push!(plt2, 1, itrj, plaq)

                plot(plt1, plt2, layout = 2)

            end

            for itrj = 1:Nsteps
                plaq = a.plaquette[itrj]

                plot_refresh!(plt1, plt2, hist_plaq, plaq, itrj)

                flush(stdout)
            end

            savefig(pwd() * "/" * a.dirname * "/Plaquette.pdf")
        end

        function plot_polyakov(dirname::String)
            a = analyze(dirname)
            plot_polyakov(a)
        end

        function plot_polyakov(a::Analyze_data)
            plt1 = histogram([0], label = nothing) #plot1
            plt2 = plot([], [], label = nothing) #plot2
            ylabel!("Polyakov loop")
            xlabel!("MC time")
            plot(plt1, plt2, layout = 2)
            hist_poly = []

            Nsteps = a.numdata

            function plot_refresh!(plt1, plt2, hist_poly, poly, itrj)
                bins = round(Int, log(itrj) * 5 + 1)
                append!(hist_poly, poly)

                plt1 = histogram(hist_poly, bins = bins, label = nothing) #plot1
                xlabel!("Polyakov loop")

                push!(plt2, 1, itrj, poly)

                plot(plt1, plt2, layout = 2)

            end

            for itrj = 1:Nsteps
                poly = a.polyakov[itrj]
                plot_refresh!(plt1, plt2, hist_poly, abs(poly), itrj)

                flush(stdout)
            end
            savefig(pwd() * "/" * a.dirname * "/Polyakov.pdf")
        end

        function plot_plaq_and_poly(dirname::String)
            a = analyze(dirname)
            plot_plaq_and_poly(a)
        end

        function plot_plaq_and_poly(a::Analyze_data)
            plt1 = histogram([0], label = nothing) #plot1
            plt2 = plot([], [], label = nothing) #plot2
            ylabel!("Plaquette")
            xlabel!("MC time")
            plt3 = histogram([0], label = nothing) #plot3
            plt4 = plot([], [], label = nothing) #plot4
            ylabel!("Polyakov loop")
            xlabel!("MC time")
            plot(plt1, plt2, plt3, plt4, layout = 4)

            hist_plaq = []
            hist_poly = []

            function plot_refresh!(
                plt1,
                plt2,
                plt3,
                plt4,
                hist_plaq,
                hist_poly,
                plaq,
                poly,
                itrj,
            )
                bins = round(Int, log(itrj) * 5 + 1)
                append!(hist_plaq, plaq)
                append!(hist_poly, poly)
                #
                plt1 = histogram(hist_plaq, bins = bins, label = nothing) #plot1
                xlabel!("Plaquette")
                plt3 = histogram(hist_poly, bins = bins, label = nothing) #plot3
                xlabel!("Polyakov loop")
                #
                push!(plt2, 1, itrj, plaq)
                push!(plt4, 1, itrj, poly)
                #
                plot(plt1, plt2, plt3, plt4, layout = 4)
                #gui()
            end

            Nsteps = a.numdata

            for itrj = 1:Nsteps
                poly = a.polyakov[itrj]
                plaq = a.plaquette[itrj]
                plot_refresh!(
                    plt1,
                    plt2,
                    plt3,
                    plt4,
                    hist_plaq,
                    hist_poly,
                    plaq,
                    abs(poly),
                    itrj,
                )

                flush(stdout)
            end
            savefig(pwd() * "/" * a.dirname * "/Plaquette_Polyakov.pdf")
        end
    end
end

end
